
/**
 * Adds a connection to the given vertex.
 */
Graph.prototype.connectVertex = function(source, direction, length, evt)
{
    var pt = (source.geometry.relative) ? new mxPoint(source.parent.geometry.width * source.geometry.x,
        source.parent.geometry.height * source.geometry.y) : new mxPoint(source.geometry.x, source.geometry.y);

    if (direction == mxConstants.DIRECTION_NORTH)
    {
        pt.x += source.geometry.width / 2;
        pt.y -= length ;
    }
    else if (direction == mxConstants.DIRECTION_SOUTH)
    {
        pt.x += source.geometry.width / 2;
        pt.y += source.geometry.height + length;
    }
    else if (direction == mxConstants.DIRECTION_WEST)
    {
        pt.x -= length;
        pt.y += source.geometry.height / 2;
    }
    else
    {
        pt.x += source.geometry.width + length;
        pt.y += source.geometry.height / 2;
    }

    var parentState = this.view.getState(this.model.getParent(source));
    var s = this.view.scale;
    var t = this.view.translate;
    var dx = t.x * s;
    var dy = t.y * s;

    if (this.model.isVertex(parentState.cell))
    {
        dx = parentState.x;
        dy = parentState.y;
    }

    // Workaround for relative child cells
    if (this.model.isVertex(source.parent) && source.geometry.relative)
    {
        pt.x += source.parent.geometry.x;
        pt.y += source.parent.geometry.y;
    }

    // Checks actual end point of edge for target cell
    var target = (mxEvent.isControlDown(evt)) ? null : this.getCellAt(dx + pt.x * s, dy + pt.y * s);

    if (this.model.isAncestor(target, source))
    {
        target = null;
    }

    // Checks if target or ancestor is locked
    var temp = target;

    while (temp != null)
    {
        if (this.isCellLocked(temp))
        {
            target = null;
            break;
        }

        temp = this.model.getParent(temp);
    }

    // Checks if source and target intersect
    if (target != null)
    {
        var sourceState = this.view.getState(source);
        var targetState = this.view.getState(target);

        if (sourceState != null && targetState != null && mxUtils.intersects(sourceState, targetState))
        {
            target = null;
        }
    }

    var duplicate = !mxEvent.isShiftDown(evt);

    if (duplicate)
    {
        if (direction == mxConstants.DIRECTION_NORTH)
        {
            pt.y -= source.geometry.height / 2;
        }
        else if (direction == mxConstants.DIRECTION_SOUTH)
        {
            pt.y += source.geometry.height / 2;
        }
        else if (direction == mxConstants.DIRECTION_WEST)
        {
            pt.x -= source.geometry.width / 2;
        }
        else
        {
            pt.x += source.geometry.width / 2;
        }
    }

    // Uses connectable parent vertex if one exists
    if (target != null && !this.isCellConnectable(target))
    {
        var parent = this.getModel().getParent(target);

        if (this.getModel().isVertex(parent) && this.isCellConnectable(parent))
        {
            target = parent;
        }
    }

    if (target == source || this.model.isEdge(target) || !this.isCellConnectable(target))
    {
        target = null;
    }

    var result = [];

    this.model.beginUpdate();
    try
    {
        var realTarget = target;

        if (realTarget == null && duplicate)
        {
            // Handles relative children
            var cellToClone = source;
            var geo = this.getCellGeometry(source);

            while (geo != null && geo.relative)
            {
                cellToClone = this.getModel().getParent(cellToClone);
                geo = this.getCellGeometry(cellToClone);
            }

            // Handle consistuents for cloning
            var state = this.view.getState(cellToClone);
            var style = (state != null) ? state.style : this.getCellStyle(cellToClone);

            if (mxUtils.getValue(style, 'part', false))
            {
                var tmpParent = this.model.getParent(cellToClone);

                if (this.model.isVertex(tmpParent))
                {
                    cellToClone = tmpParent;
                }
            }

            var nLabel=getObjectNameInfo(vertexValue);//获取最新的名称+编号
            realTarget = this.duplicateCells([cellToClone], false)[0];
            var newValue=mxUtils.parseXml(mxUtils.getXml(vertexValue)).documentElement
            this.getModel().setValue(realTarget,newValue);//创建目标对象
            realTarget.setAttribute('label',nLabel);

            var geo = this.getCellGeometry(realTarget);
            geo.x = pt.x - geo.width / 2;
            geo.y = pt.y - geo.height / 2;
        }

        // Never connects children in stack layouts
        var layout = null;

        if (this.layoutManager != null)
        {
            layout = this.layoutManager.getLayout(this.model.getParent(source));
        }
        //自动增加对象创建连线
        var newValue=mxUtils.parseXml(mxUtils.getXml(edgeValue)).documentElement;
        var edge = ((mxEvent.isControlDown(evt) && duplicate) || (target == null && layout != null && layout.constructor == mxStackLayout)) ? null :
            this.insertEdge(this.model.getParent(source), null, newValue, source, realTarget, this.createCurrentEdgeStyle());

        // Inserts edge before source
        if (edge != null && this.connectionHandler.insertBeforeSource)
        {
            var index = null;
            var tmp = source;

            while (tmp.parent != null && tmp.geometry != null &&
            tmp.geometry.relative && tmp.parent != edge.parent)
            {
                tmp = this.model.getParent(tmp);
            }

            if (tmp != null && tmp.parent != null && tmp.parent == edge.parent)
            {
                var index = tmp.parent.getIndex(tmp);
                tmp.parent.insert(edge, index);
            }
        }

        // Special case: Click on west icon puts clone before cell
        if (target == null && realTarget != null && layout != null && source.parent != null &&
            layout.constructor == mxStackLayout && direction == mxConstants.DIRECTION_WEST)
        {
            var index = source.parent.getIndex(source);
            source.parent.insert(realTarget, index);
        }

        if (edge != null)
        {
            // Uses elbow edges with vertical or horizontal direction
			// var elbowValue = (direction == mxConstants.DIRECTION_NORTH || direction == mxConstants.DIRECTION_SOUTH) ? 'vertical' : 'horizontal';
			// edge.style = mxUtils.setStyle(edge.style, 'edgeStyle', 'elbowEdgeStyle');
			// edge.style = mxUtils.setStyle(edge.style, 'elbow', elbowValue);
            result.push(edge);
        }

        if (target == null && realTarget != null)
        {
            result.push(realTarget);
        }

        if (realTarget == null && edge != null)
        {
            edge.geometry.setTerminalPoint(pt, false);
        }

        if (edge != null)
        {
            this.fireEvent(new mxEventObject('cellsInserted', 'cells', [edge]));
        }
    }
    finally
    {
        this.model.endUpdate();
    }

    return result;
};

var getLabelOld = Graph.prototype.getLabel;
/**
 * 重写获取标签的方法
 * @param cell
 * @returns {HTMLDivElement|*}
 */
Graph.prototype.getLabel = function (cell) {
    var state = this.view.getState(cell);
    var isModelObj = cell.value != null && typeof (cell.value) == 'object';
    if (state != null && mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, !0) == !1) {
        var oldLabel;
        if (isModelObj){
            oldLabel = cell.value.getAttribute('label');
        } else {
            oldLabel = cell.value;
        }
        var label = '';
        for (let i = 0; i < oldLabel.length; i++) {
            label += oldLabel.charAt(i);
            if (i<oldLabel.length - 1) {
                // label += '<br/>';
            }
        }
        if (isModelObj) {
            var div = document.createElement('div');
            div.innerHTML = label;
            return label;
        } else {
            return label;
        }

    } else {
        return getLabelOld.apply(this, arguments);
    }
}
